package bank.jms;

import java.io.IOException;
import java.util.Hashtable;

import javax.jms.JMSException;
import javax.jms.ObjectMessage;
import javax.jms.Queue;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueReceiver;
import javax.jms.QueueSender;
import javax.jms.QueueSession;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

import org.apache.activemq.ActiveMQConnection;

import bank.Bank;
import bank.BankDriver;
import bank.InactiveException;
import bank.OverdrawException;
import bank.local.LocalDriver;
import bank.transport.Answer;
import bank.transport.Request;

public class JMSServer {
	// bank used by server
	public static Bank bank;
	public static QueueSender sender;
	public static QueueReceiver receiver = null;
	public static QueueSession session = null;
	public static BankDriver driver = new LocalDriver();

	/**
	 * Main method of the JMS bank server.
	 * 
	 * @param args
	 */
	public static void main(String[] args) {
			try {
				driver.connect(null);
			} catch (IOException e) {
				System.out.println("Connecting failed");
			}
			bank = driver.getBank();
			Hashtable<String, String> properties = new Hashtable<String,
			String>();
			properties.put(Context.INITIAL_CONTEXT_FACTORY,
			"org.apache.activemq.jndi.ActiveMQInitialContextFactory");
			properties.put(Context.PROVIDER_URL, "tcp://localhost:61616");
			properties.put("queue.BANK", "example.BANK");
			QueueConnection connection = null;
			try {
				Context context = new InitialContext(properties);
				QueueConnectionFactory factory = (QueueConnectionFactory) context.lookup("ConnectionFactory");
				Queue queue = (Queue) context.lookup("BANK");
				connection = factory.createQueueConnection(
						ActiveMQConnection.DEFAULT_USER,
						ActiveMQConnection.DEFAULT_PASSWORD);
						session = connection.createQueueSession(false,
						QueueSession.AUTO_ACKNOWLEDGE);
						sender = session.createSender(queue);
						receiver = session.createReceiver(queue);
						connection.start();
			} catch (JMSException e) {
				System.out.println("Connection failed");
			} catch (NamingException e) {
				System.out.println("Queue not found");
			}
			
			while (true) {
				try {
					ObjectMessage request = (ObjectMessage) receiver.receive();
					Queue replyQueue = (Queue) request.getJMSReplyTo();
					QueueSender tempSender = session.createSender(replyQueue);
					Answer answer = receiveRequest((Request) request.getObject());
					ObjectMessage response = session.createObjectMessage();
					response.setObject(answer);
					tempSender.send(response);
				} catch (JMSException ex) {
				} catch (ClassCastException ex) {
					System.err.println("Probably a wrong request has been sent.");
				} catch (IllegalArgumentException e) {
					e.printStackTrace();
				} catch (IOException e) {
					e.printStackTrace();
				} catch (InactiveException e) {
					e.printStackTrace();
				} catch (OverdrawException e) {
					e.printStackTrace();
				}
				}
			
	}
	
	// Take a request and do correponding action
		private static Answer receiveRequest(Request r) throws IOException, IllegalArgumentException, InactiveException, OverdrawException {
			if (r.str1.equals("createAccount")) {
				
				return new Answer(bank.createAccount(r.str2));
			} else if (r.str1.equals("removeAccount")){
				return new Answer(bank.removeAccount(r.str2));
			} else if (r.str1.equals("getAccountNumbers")){
				return new Answer(bank.getAccountNumbers());
			} else if (r.str1.equals("getAccount")){
				return new Answer(bank.getAccount(r.str2));
			} else if (r.str1.equals("transfer")){
				bank.transfer(r.acc1, r.acc2, r.dbl1);
			} else if (r.str1.equals("deposit")){
				bank.getAccount(r.str2).deposit(r.dbl1);
			} else if (r.str1.equals("withdraw")){
				bank.getAccount(r.str2).withdraw(r.dbl1);
			}
	 
			return null;
		}
	
}
